home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Online / Qpopper / pop_pass.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-24  |  16.3 KB  |  638 lines

  1. /*
  2.  * Copyright (c) 1989 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #ifndef lint
  8. static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
  9. static char SccsId[] = "@(#)@(#)pop_pass.c    2.3  2.3 4/2/91";
  10. #endif not lint
  11.  
  12. #include <stdio.h>
  13. #include <sys/types.h>
  14. #if defined(SYSV) || defined(AIX)
  15. # include <string.h>
  16. #else
  17. # include <strings.h>
  18. #endif
  19.  
  20. #include <pwd.h>
  21. #include "popper.h"
  22.  
  23. #define    SLEEP_SECONDS 10
  24.  
  25.  
  26. /* This error message is vague on purpose to help reduce help improve
  27.    security at the inconvience of administrators and users */
  28.  
  29. char    *pwerrmsg = "Password supplied for \"%s\" is incorrect.";
  30.  
  31.  
  32. #ifdef NONAUTHFILE
  33. checknonauthfile(user) 
  34.      char *user;
  35. {
  36.     char buf[MAXUSERNAMELEN+1];
  37.     FILE *fp;
  38.     char cool = 0;
  39.  
  40.     if ((fp = fopen(NONAUTHFILE, "r")) != NULL) {
  41.     while (fgets(buf, MAXUSERNAMELEN+1, fp)) {
  42.         buf[strlen(buf) -1] = '\0';
  43.         if (!strcmp(buf, user)) {
  44.         fclose(fp);
  45.         return(-1);
  46.         }
  47.     }
  48.  
  49.     fclose(fp);
  50.     }
  51.     return(0);
  52. }
  53. #endif
  54.  
  55. #ifdef AUTHFILE
  56. checkauthfile(user) 
  57.      char *user;
  58. {
  59.     char buf[MAXUSERNAMELEN+1];
  60.     FILE *fp;
  61.     char cool = 0;
  62.  
  63.     if ((fp = fopen(AUTHFILE, "r")) != NULL) {
  64.     while (fgets(buf, MAXUSERNAMELEN+1, fp)) {
  65.         buf[strlen(buf) -1] = '\0';
  66.         if (!strcmp(buf, user)) {
  67.         fclose(fp);
  68.         return(0);
  69.         }
  70.     }
  71.  
  72.     fclose(fp);
  73.     }
  74.     return(-1);
  75. }
  76. #endif
  77.  
  78. int auth_user_kerberos (p, pw)
  79. POP     *   p;
  80. struct passwd *pw;
  81. {
  82. #ifdef KERBEROS
  83.     char lrealm[REALM_SZ];
  84.     int status;
  85.     struct passwd *pwp;
  86.  
  87.     if ((status = krb_get_lrealm(lrealm,1)) == KFAILURE) {
  88.         pop_log(p, LOG_WARNING, "%s: (%s.%s@%s) %s", p->client, kdata.pname, 
  89.         kdata.pinst, kdata.prealm, krb_err_txt[status]);
  90.         return(pop_msg(p,POP_FAILURE,
  91.             "Kerberos error:  \"%s\".", krb_err_txt[status]));
  92.     }
  93.  
  94. # ifdef KUSEROK
  95.     if (kuserok(&kdata, p->user)) {
  96.         pop_log(p, LOG_WARNING, "%s: (%s.%s@%s): not in %s's ACL.",
  97.         p->client, kdata.pname, kdata.pinst, kdata.prealm, p->user);
  98.     return(pop_msg(p,POP_FAILURE, "Not in %s's ACL.", p->user));
  99.     }
  100. # else
  101.     if (strcmp(kdata.prealm,lrealm))  {
  102.          pop_log(p, LOG_WARNING, "%s: (%s.%s@%s) realm not accepted.", 
  103.          p->client, kdata.pname, kdata.pinst, kdata.prealm);
  104.      return(pop_msg(p,POP_FAILURE,
  105.              "Kerberos realm \"%s\" not accepted.", kdata.prealm));
  106.     }
  107.  
  108.     if (strcmp(kdata.pinst,"")) {
  109.         pop_log(p, LOG_WARNING, "%s: (%s.%s@%s) instance not accepted.", 
  110.          p->client, kdata.pname, kdata.pinst, kdata.prealm);
  111.         return(pop_msg(p,POP_FAILURE,
  112.           "Must use null Kerberos(tm) instance -  \"%s.%s\" not accepted.",
  113.           kdata.pname, kdata.pinst));
  114.     }
  115. # endif /* KUSEROK */
  116.     return(POP_SUCCESS);
  117. #else    /* Kerberos not defined */
  118.     return(pop_log(p, LOG_WARNING,
  119.     "Kerberos failure: The popper has not been compiled with -DKERBEROS"));
  120. #endif    /* KERBEROS */
  121. }
  122.  
  123.  
  124. #ifdef AUTH
  125.     char *crypt();
  126.  
  127. #if defined(SUNOS4) && !defined(ISC)
  128.  
  129. #include <sys/label.h>
  130. #include <sys/audit.h>
  131. #include <pwdadj.h>
  132.  
  133. static int
  134. auth_user(p, pw)
  135. POP     *   p;
  136. struct passwd *pw;
  137. {
  138.     struct passwd_adjunct *pwadj;
  139.  
  140.     /*  Look for the user in the shadow password file */
  141.     if ((pwadj = getpwanam(p->user)) == NULL) {
  142.     sleep(SLEEP_SECONDS);
  143.     return (pop_msg(p,POP_FAILURE,
  144.         "(shadow) Password supplied for \"%s\" is empty.",p->user));
  145.     } else {
  146.         pw->pw_passwd = (char *)strdup(pwadj->pwa_passwd);
  147.     }
  148.  
  149.     /*  We don't accept connections from users with null passwords */
  150.     /*  Compare the supplied password with the password file entry */
  151.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
  152.         strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  153.     sleep(SLEEP_SECONDS);
  154.     return (pop_msg(p,POP_FAILURE,pwerrmsg, p->user));
  155.     }
  156.  
  157.     return(POP_SUCCESS);
  158. }
  159.  
  160. #endif    /* SUNOS4 */
  161.  
  162. #if defined(SOLARIS2) || defined(AUX)
  163.  
  164. #include <shadow.h>
  165.  
  166. static int
  167. auth_user(p, pw)
  168. POP     *   p;
  169. struct passwd *pw;
  170. {
  171.     register struct spwd * pwd;
  172.     long today;
  173.  
  174.     /*  Look for the user in the shadow password file */
  175.     if ((pwd = getspnam(p->user)) == NULL) {
  176.         if (!strcmp(pw->pw_passwd, "x")) {    /* This my be a YP entry */
  177.         sleep(SLEEP_SECONDS);
  178.         return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  179.     }
  180.     } else {
  181.     today = (long)time((time_t *)NULL)/24/60/60;
  182.  
  183.     /* Check for expiration date */
  184.     if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
  185.         sleep(SLEEP_SECONDS);
  186.         return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
  187.     }
  188.  
  189.     /* Check if password is valid */
  190.     if (pwd->sp_max > 0 && today > pwd->sp_lstchg+pwd->sp_max) {
  191.         sleep(SLEEP_SECONDS);
  192.         return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
  193.     }
  194.  
  195.     pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
  196.     endspent();
  197.     }
  198.  
  199.     /*  We don't accept connections from users with null passwords */
  200.     /*  Compare the supplied password with the password file entry */
  201.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
  202.         strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  203.     sleep(SLEEP_SECONDS);
  204.     return (pop_msg(p, POP_FAILURE, pwerrmsg, p->user));
  205.     }
  206.  
  207.     return(POP_SUCCESS);
  208. }
  209.  
  210. #endif    /* SOLARIS2 || AUX */
  211.  
  212. #if defined(PTX) || defined(ISC)
  213.  
  214. #include <shadow.h>
  215.  
  216. static int
  217. auth_user(p, pw)
  218. POP     *   p;
  219. struct passwd *pw;
  220. {
  221.     register struct spwd * pwd;
  222.     long today;
  223.  
  224.     /*  Look for the user in the shadow password file */
  225.     if ((pwd = getspnam(p->user)) == NULL) {
  226.         if (!strcmp(pw->pw_passwd, "x")) {    /* This my be a YP entry */
  227.         sleep(SLEEP_SECONDS);
  228.         return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  229.     }
  230.     } else {
  231.     pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
  232.     }
  233.  
  234.     /*  We don't accept connections from users with null passwords */
  235.     /*  Compare the supplied password with the password file entry */
  236.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
  237.         strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  238.     sleep(SLEEP_SECONDS);
  239.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  240.     }
  241.  
  242.     return(POP_SUCCESS);
  243. }
  244.  
  245. #endif    /* PTX */
  246.  
  247. #if defined(POPSCO) || defined(HPUX10)
  248.  
  249. #ifdef POPSCO
  250. # include <sys/security.h>
  251. # include <sys/audit.h>
  252. #else
  253. # include <hpsecurity.h>
  254. #endif
  255.  
  256. #include <prot.h>
  257. #define PASSWD(p)    p->ufld.fd_encrypt
  258.  
  259. static int
  260. auth_user(p, pw)
  261. POP     *   p;
  262. struct passwd *pw;
  263. {
  264.     register struct pr_passwd *pr;
  265.  
  266.     if ((pr = getprpwnam(p->user)) == NULL) {
  267.         if (!strcmp(pw->pw_passwd, "x")) {
  268.         sleep(SLEEP_SECONDS);
  269.         return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  270.     }
  271.  
  272.     /*  We don't accept connections from users with null passwords */
  273.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
  274.              (strcmp(bigcrypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
  275.           strcmp(crypt (p->pop_parm[1], pw->pw_passwd), pw->pw_passwd))) {
  276.         sleep(SLEEP_SECONDS);
  277.         return(pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  278.     }
  279.     } else {
  280.     /*  We don't accept connections from users with null passwords */
  281.     /*  Compare the supplied password with the password file entry */
  282.     if ((PASSWD(pr) == NULL) || (*PASSWD(pr) == '\0')) {
  283.         sleep(SLEEP_SECONDS);
  284.         return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  285.     }
  286.     
  287.     if (strcmp(bigcrypt(p->pop_parm[1], PASSWD(pr)), PASSWD(pr)) &&
  288.             strcmp(crypt(p->pop_parm[1], PASSWD(pr)), PASSWD(pr))) {
  289.         sleep(SLEEP_SECONDS);
  290.         return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  291.     }
  292.     }
  293.  
  294.     return(POP_SUCCESS);
  295. }
  296.  
  297. #endif    /* POPSCO || HPUX10 */
  298.  
  299. #ifdef ULTRIX
  300.  
  301. #include <auth.h>
  302.  
  303. static int
  304. auth_user(p, pw)
  305. struct passwd  *   pw;
  306. POP     *   p;
  307. {
  308.     AUTHORIZATION *auth, *getauthuid();
  309.  
  310.     if ((auth = getauthuid(pw->pw_uid)) == NULL) {
  311.         if (!strcmp(pw->pw_passwd, "x")) {    /* This my be a YP entry */
  312.         sleep(SLEEP_SECONDS);
  313.         return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  314.     }
  315.     } else {
  316.     pw->pw_passwd = (char *)strdup(auth->a_password);
  317.     }
  318.  
  319.     /*  We don't accept connections from users with null passwords */
  320.     /*  Compare the supplied password with the password file entry */
  321.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0')) {
  322.     sleep(SLEEP_SECONDS);
  323.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  324.     }
  325.  
  326.     if (strcmp(crypt16(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
  327.         strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  328.     sleep(SLEEP_SECONDS);
  329.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  330.     }
  331.  
  332.     return(POP_SUCCESS);
  333. }
  334.  
  335. #endif    /* ULTRIX */
  336.  
  337. #ifdef OSF1
  338. #include <sys/types.h>
  339. #include <sys/security.h>
  340. #include <prot.h>
  341. #define   PASSWD(p)   (p->ufld.fd_encrypt)
  342. static int
  343. auth_user(p, pw)
  344. POP     *   p;
  345. struct passwd *pw;
  346. {
  347.     register struct pr_passwd *pr;
  348.  
  349.     if ((pr = getprpwnam(p->user)) == NULL) {
  350.         if (!strcmp(pw->pw_passwd, "x")) {    /* This my be a YP entry */
  351.         sleep(SLEEP_SECONDS);
  352.         return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  353.     }
  354.     } else {
  355.     pw->pw_passwd = (char *)strdup(PASSWD(pr));
  356.     }
  357.  
  358.     /*  We don't accept connections from users with null passwords */
  359.     /*  Compare the supplied password with the password file entry */
  360.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0')) {
  361.     sleep(SLEEP_SECONDS);
  362.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  363.     }
  364.  
  365.     if (strcmp(bigcrypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
  366.         strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  367.     sleep(SLEEP_SECONDS);
  368.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  369.     }
  370.  
  371.     return(POP_SUCCESS);
  372. }
  373.  
  374. #endif        /* OSF1 */
  375.  
  376. #ifdef UNIXWARE
  377.  
  378. #include <shadow.h>
  379.  
  380. static int
  381. auth_user(p, pw)
  382. struct passwd  *   pw;
  383. POP     *   p;
  384. {
  385.     register struct spwd * pwd;
  386.     long today;
  387.  
  388.     /*  Look for the user in the shadow password file */
  389.     if ((pwd = getspnam(p->user)) == NULL) {
  390.         if (!strcmp(pw->pw_passwd, "x")) {    /* This my be a YP entry */
  391.         sleep(SLEEP_SECONDS);
  392.         return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  393.     }
  394.     } else {
  395.     today = (long)time((time_t *)NULL)/24/60/60;
  396.  
  397.     /* Check for expiration date */
  398.     if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
  399.         sleep(SLEEP_SECONDS);
  400.         return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
  401.     }
  402.  
  403.     /* Check if password is valid */
  404.     if (pwd->sp_max > 0 && today > pwd->sp_lstchg+pwd->sp_max) {
  405.         sleep(SLEEP_SECONDS);
  406.         return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
  407.     }
  408.  
  409.     pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
  410.     endspent();
  411.     }
  412.  
  413.     /*  We don't accept connections from users with null passwords */
  414.     /*  Compare the supplied password with the password file entry */
  415.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
  416.         strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  417.     sleep(SLEEP_SECONDS);
  418.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  419.     }
  420.  
  421.     return(POP_SUCCESS);
  422. }
  423.  
  424. #endif    /* UNIXWARE */
  425.  
  426. #ifdef LINUX
  427. #include <shadow.h>
  428.  
  429. static int
  430. auth_user(p, pw)
  431. POP     *   p;
  432. struct passwd *pw;
  433. {
  434.     register struct spwd * pwd;
  435.     long today;
  436.  
  437.     /*  Look for the user in the shadow password file */
  438.     if ((pwd = getspnam(p->user)) == NULL) {
  439.         if (!strcmp(pw->pw_passwd, "x")) {    /* This my be a YP entry */
  440.         sleep(SLEEP_SECONDS);
  441.         return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  442.     }
  443.     } else {
  444.     today = (long)time((time_t *)NULL)/24/60/60;
  445.  
  446.     /* Check for expiration date */
  447.     if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
  448.         sleep(SLEEP_SECONDS);
  449.         return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
  450.     }
  451.  
  452.     /* Check if password is valid */
  453.     if (pwd->sp_max > 0 && today > pwd->sp_lstchg+pwd->sp_max) {
  454.         sleep(SLEEP_SECONDS);
  455.         return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
  456.     }
  457.  
  458.     pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
  459.     endspent();
  460.     }
  461.  
  462.     /*  We don't accept connections from users with null passwords */
  463.     /*  Compare the supplied password with the password file entry */
  464.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') || 
  465.         (strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
  466.          strcmp(pw_encrypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd))){
  467.     sleep(SLEEP_SECONDS);
  468.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  469.     }
  470.  
  471.     return(POP_SUCCESS);
  472. }
  473.  
  474. #endif  /* LINUX */
  475.  
  476. #else    /* NOT AUTH */
  477.  
  478. char *crypt();
  479.  
  480. static int
  481. auth_user(p, pw)
  482. POP     *   p;
  483. struct passwd  *   pw;
  484. {
  485.     /*  We don't accept connections from users with null passwords */
  486.     /*  Compare the supplied password with the password file entry */
  487.  
  488.     if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
  489.         strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
  490.     sleep(SLEEP_SECONDS);
  491.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  492.     }
  493.  
  494.     return(POP_SUCCESS);
  495. }
  496.  
  497. #endif    /* AUTH */
  498.  
  499. /* 
  500.  *  pass:   Obtain the user password from a POP client
  501.  */
  502.  
  503. #ifdef SECURENISPLUS
  504. /* AUTH gets defined in rpc/... */
  505. # ifdef AUTH
  506. #  undef AUTH
  507. # endif
  508. # include <rpc/rpc.h>
  509. # include <rpc/key_prot.h>
  510. #endif
  511.  
  512. int pop_pass (p)
  513. POP     *   p;
  514. {
  515.     struct passwd pw, *pwp;
  516. #ifdef CHECK_SHELL
  517.     char *getusershell();
  518.     void endusershell();
  519.     char *shell;
  520.     char *cp;
  521.     int shellvalid;
  522. #endif
  523.  
  524. #ifdef SECURENISPLUS
  525.     UID_T uid_save;
  526.     char net_name[MAXNETNAMELEN],
  527.      secretkey[HEXKEYBYTES + 1];
  528.  
  529.     *secretkey = '\0';
  530. #endif
  531.  
  532. #ifdef NONAUTHFILE
  533.     /* Is the user not authorized to use POP? */
  534.     if (checknonauthfile(p->user) != 0) {
  535.     sleep(SLEEP_SECONDS);
  536.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  537.     }
  538. #endif
  539.  
  540. #ifdef AUTHFILE
  541.     /* Is the user authorized to use POP? */
  542.     if (checkauthfile(p->user) != 0) {
  543.     sleep(SLEEP_SECONDS);
  544.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  545.     }
  546. #endif
  547.  
  548.     /*  Look for the user in the password file */
  549.     if ((pwp = getpwnam(p->user)) == NULL) {
  550.     sleep(SLEEP_SECONDS);
  551.     return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  552.     }
  553.  
  554.     pw = *pwp;
  555.  
  556. #ifdef SECURENISPLUS
  557.     /*  we must do this keyserv stuff (as well as auth_user()!) as the user */
  558.     uid_save = geteuid();
  559.     seteuid(pw.pw_uid);
  560.  
  561.     /*  see if DES keys are already known to the keyserv(1m) */
  562.     if (! key_secretkey_is_set()) {
  563.     /*  keys are not known, so we must get the DES keys
  564.         and register with the keyserv(1m) */
  565.  
  566.     getnetname(net_name);
  567.  
  568.     if (getpublickey(net_name, secretkey)) {
  569.         if (strlen(p->pop_parm[1]) > 8) (p->pop_parm[1])[8] = '\0';
  570.  
  571.         if (! getsecretkey(net_name, secretkey, p->pop_parm[1]) ||
  572.                             *secretkey == '\0') {
  573.         sleep(SLEEP_SECONDS);
  574.         return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
  575.         }
  576.  
  577.         key_setsecret(secretkey);
  578.         memset(secretkey, '\0', sizeof(secretkey));
  579.     } else {
  580.         /* if there are no keys defined, we assume that password entry
  581.            either resides in /etc/shadow or "root" has access to the
  582.            corresponding NIS+ entry */
  583.         seteuid(0);
  584.     }
  585.     }
  586. #endif
  587.  
  588. #ifdef BLOCK_UID
  589.     if (pw.pw_uid <= BLOCK_UID)
  590.     return (pop_msg(p,POP_FAILURE,
  591.                 "Access is blocked for UIDs below %d", BLOCK_UID));
  592. #endif
  593.  
  594. #ifdef CHECK_SHELL
  595.     /*  Disallow anyone who does not have a standard shell as returned by
  596.      *  getusershell(), unless the sys admin has included the wildcard
  597.      *  shell in /etc/shells.  (default wildcard - /POPPER/ANY/SHELL)
  598.      */
  599.     if ((shell = pw.pw_shell) == NULL || *shell == 0)
  600. /* You can default the shell, but I don't think it's a good idea */
  601. /*    shell = "/usr/bin/sh"; */
  602.     return(pop_msg(p, POP_FAILURE, "No user shell defined"));
  603.     
  604.     for (shellvalid = 0; !shellvalid && ((cp = getusershell()) != NULL);)
  605.     if (!strcmp(cp, WILDCARD_SHELL) || !strcmp(cp, shell))
  606.          shellvalid = 1;
  607.     endusershell();
  608.  
  609.     if (!shellvalid)
  610.     return(pop_msg(p, POP_FAILURE, "\"%s\": shell not found.", p->user));
  611. #endif
  612.  
  613.     if ((p->kerberos ? auth_user_kerberos(p, pw) : auth_user(p, pwp))
  614.                             != POP_SUCCESS) {
  615.         pop_log(p,POP_PRIORITY,"Failed attempted login to %s from host %s",
  616.                                 p->user, p->client);
  617.     return(POP_FAILURE);
  618.     }
  619.  
  620. #ifdef SECURENISPLUS
  621.     seteuid(uid_save);
  622. #endif
  623.  
  624.     /*  Make a temporary copy of the user's maildrop */
  625.     /*    and set the group and user id */
  626.     /*    and get information about the maildrop */
  627.     if (pop_dropcopy(p, &pw) != POP_SUCCESS) return (POP_FAILURE);
  628.  
  629.     /*  Initialize the last-message-accessed number */
  630.     p->last_msg = 0;
  631.  
  632.     /*  Authorization completed successfully */
  633.     return (pop_msg (p,POP_SUCCESS,
  634.         "%s has %d message%s (%d octets).",
  635.             p->user,p->msg_count, p->msg_count == 1 ? "" : "s", p->drop_size));
  636. }
  637.  
  638.